/* Copyright (C) 
 * 
 * Disclaim
 * This program is the property of AI Speech Ltd. It shall be communicated to
 * authorized personnel only. It is not to be disclosed outside the group without
 * prior written consent. If you are not sure if you’re authorized to read this
 * program, please contact info@aispeech.com before reading.
 * 
 */

/**
 * @file wtk_utils_str_iter.c
 * 
 * @author wxm71(weixing.mei@aispeech.com)
 * 
 * @version 0.0.2
 * 
 * @date 2014-12-03
 */


#include "wtk/utils/wtk_utils_str_iter.h"
#include "wtk/utils/wtk_utils.h"

#include <ctype.h>


#define wtk_str_iter_set_data(iter, data, len) {iter.data = data; iter.dataEnd = data+len; iter.ptr = data; }
#define wtk_str_iter_is_empty(iter) (NULL==(iter->data) || (iter)->data==(iter)->dataEnd)
#define wtk_str_iter_is_end(iter)   ((iter)->ptr>=(iter)->dataEnd)

int wtk_str_iter_cnt(wtk_str_iter_t *iter) {
    wtk_string_t val;
    int cnt = 0;

    do {
        val = wtk_str_iter_next(iter);
        if(val.len>0) {
            ++cnt;
        } else {
            break;
        }
    } while(1);

    return cnt;
}



static wtk_string_t wtk_char_split_iter_next(wtk_str_iter_t *iter) {
    wtk_string_t str;
    str.data = NULL;
    str.len = 0;

    if(wtk_str_iter_is_empty(iter) || wtk_str_iter_is_end(iter)) {
        goto end;
    }

    str.data = iter->ptr;
    do {
        ++iter->ptr;
    } while(!wtk_str_iter_is_end(iter) && *iter->ptr!=iter->sep.c);
    str.len = iter->ptr-str.data;

    // skip the sep character
    ++iter->ptr;
end:
    return str;
}



static wtk_string_t wtk_cset_split_iter_next(wtk_str_iter_t *iter) {
    wtk_string_t str;
    str.data = NULL;
    str.len = 0;

    if(wtk_str_iter_is_empty(iter) || wtk_str_iter_is_end(iter)) {
        goto end;
    }

    str.data = iter->ptr;
    do {
        ++iter->ptr;
    } while(!wtk_str_iter_is_end(iter) && -1==wtk_str_str(iter->sep.str.data, iter->sep.str.len, iter->ptr, 1) );
    str.len = iter->ptr-str.data;

    // skip the sep character
    ++iter->ptr;
end:
    return str;
}



static wtk_string_t wtk_str_split_iter_next(wtk_str_iter_t* iter) {
    wtk_string_t str;
    str.data = NULL;
    str.len = 0;

    if(wtk_str_iter_is_empty(iter) || wtk_str_iter_is_end(iter)) {
        goto end;
    }

    str.data = iter->ptr;

    int pos;
    if(!wtk_str_iter_is_end(iter)) {
        pos = wtk_str_str(iter->ptr, iter->dataEnd-iter->ptr, iter->sep.str.data, iter->sep.str.len); 
        if (-1==pos) {
            iter->ptr = iter->dataEnd;
        } else {
            iter->ptr += pos;
        }
    }
    str.len = iter->ptr-str.data;

    // skip seperator
    iter->ptr += iter->sep.str.len;

end:
    return str;
}



static wtk_string_t wtk_sset_split_iter_next(wtk_str_iter_t* iter) {
    wtk_string_t str;
    str.data = NULL;
    str.len = 0;

    if(wtk_str_iter_is_empty(iter) || wtk_str_iter_is_end(iter)) {
        goto end;
    }

    iter->ptr += iter->sep.str.len;
    str.data = iter->ptr;

    int i;
    int pos;
    wtk_string_t *ref;
    if(!wtk_str_iter_is_end(iter)) {
        for(i=0; i<iter->sep.arr->nslot; ++i) {
            ref = wtk_utils_array_get_val(iter->sep.arr, i, wtk_string_t*);

            pos = wtk_str_str(iter->ptr, iter->dataEnd-iter->ptr, ref->data, ref->len);
            if(-1!=pos) {
                iter->ptr += pos;
                break;
            }
        }

        if(-1==pos) {
            iter->ptr = iter->dataEnd;
        }
    }
    str.len = iter->ptr-str.data;

    // skip seperator
    iter->ptr = str.data + str.len;

end:
    return str;
}


static wtk_string_t wtk_wrd_iter_next(wtk_str_iter_t* iter) {
    wtk_string_t str;
    str.data = NULL;
    str.len = 0;

    if(wtk_str_iter_is_empty(iter) || wtk_str_iter_is_end(iter)) {
        goto end;
    }

    // skip leading space
    while( !wtk_str_iter_is_end(iter) && isspace(*(iter->ptr)) ) {
        ++iter->ptr;
    }

    if (wtk_str_iter_is_end(iter)) {
        goto end;
    }

    str.data = iter->ptr;

    do {
        ++iter->ptr;
    } while( !wtk_str_iter_is_end(iter) && !isspace(*(iter->ptr)) );
    str.len = iter->ptr-str.data;

    // skip seperator
    ++iter->ptr;

end:
    return str;
}


static wtk_string_t wtk_utf8_iter_next(wtk_str_iter_t* iter) {
    wtk_string_t str;
    str.data = NULL;
    str.len = 0;

    if(wtk_str_iter_is_empty(iter) || wtk_str_iter_is_end(iter)) {
        goto end;
    }

    while (!wtk_str_iter_is_end(iter) && isspace(*iter->ptr)){
        ++iter->ptr;
    }

    if(wtk_str_iter_is_end(iter)) {
        goto end;
    }

    int len = wtk_utf8_bytes(*iter->ptr);

    str.data = iter->ptr;
    str.len = len;
    iter->ptr += len;

end:
    return str;
}



wtk_str_iter_t wtk_char_split_iter(char *data, int len, char sp) {
    wtk_str_iter_t iter;
    wtk_str_iter_set_data(iter, data, len);

    iter.sep.c = sp;

    iter.hand = wtk_char_split_iter_next;

    return iter;
}


wtk_str_iter_t wtk_cset_split_iter(char *data, int len, char *sep, int snum) {
    wtk_str_iter_t iter;
    wtk_str_iter_set_data(iter, data, len);

    iter.sep.str.data = sep;
    iter.sep.str.len = snum;

    iter.hand = wtk_cset_split_iter_next;

    return iter;
}


wtk_str_iter_t wtk_str_split_iter(char *data, int len, char *sep, int slen) {
    wtk_str_iter_t iter;
    wtk_str_iter_set_data(iter, data, len);

    iter.sep.str.data = sep;
    iter.sep.str.len = slen;

    iter.hand = wtk_str_split_iter_next;

    return iter;
}


wtk_str_iter_t wtk_sset_split_iter(char *data, int len, wtk_array_t *arr) {
    wtk_str_iter_t iter;
    wtk_str_iter_set_data(iter, data, len);

    iter.sep.arr = arr;

    iter.hand = wtk_sset_split_iter_next;

    return iter;
}


wtk_str_iter_t wtk_wrd_iter(char *data, int len) {
    wtk_str_iter_t iter;
    wtk_str_iter_set_data(iter, data, len);

    iter.hand = wtk_wrd_iter_next;

    return iter;
}


wtk_str_iter_t wtk_utf8_iter(char *data, int len) {
    wtk_str_iter_t iter;
    wtk_str_iter_set_data(iter, data, len);

    iter.hand = wtk_utf8_iter_next;

    return iter;
}
